// Composit type
type Person = {
    age: number
    name: string
}
const person: Person = { age: 18, name: "Smith" }

// Tuple types
let poem: [number, boolean, string];
poem = [1, true, 'love'];

// Intersaction types
interface Skier {
    slide(): void;
}
interface Puncher {
    punch(): void;
}
type Biathelete = Skier & Puncher;

class SkiPuncher implements Biathelete {
    slide(): void {
        console.log("woohu~");
    }
    punch(): void {
        console.log("huha!");
    }

}

let bi: Biathelete = new SkiPuncher;
bi.slide();
bi.punch();

// Union types
let union: boolean | number; // OK: number
union = 5;
union = true;

type StringOrError = string | Error;
type SeriesOfTypes = string | number | boolean | Error;

// 类型 = 值的集合
type Square = {
    kind: "square";
    size: number;
}
type Rectangle = {
    kind: "rectangle";
    width: number;
    height: number;
}
type Shape = Square | Rectangle;
function area(s: Shape) {
    switch (s.kind) {
        case 'square':
            // Now TypeScript *knows* that `s` must be a square ;)
            // So you can use its members safely :)
            return s.size * s.size;
        case 'rectangle':
            return s.width * s.height;
    }
}

// Arry type
const names: string[] = ['James', 'Nick', 'Rebecca', 'Lily'];

// Function type
let sayHello: (name: string) => string;
sayHello = function (name) {
    return 'Hello ' + name;
};

// Object type
let student: {
    name: string;
    heightInCentimeters: number;
};
student = {
    name: 'Mark',
    heightInCentimeters: 183
};

// var, let, const
// var 的作用域是整个函数体，无论变量声明的位置
// let 和 const 的作用域是变量声明所在 {} 的范围内
// const 必须在声明时赋初值，并且声明之后不可变
const dog = {
    age: 3
}
dog.age = 5  // const 仅仅限制顶层修改，对底层修改不做任何限制（相当于 C++ 顶层 const 指针）
console.log(dog)

// === 与 ==
// js 中两者有区别，因为可以对不同类型的变量进行比较
// === 严格判断类型不同则直接返回 false
// == 如果类型不同则尝试类型转换，返回转换后的比较结果
// ts 中如果类型不同则编译报错，因此两者基本无区别，除了以下情况
console.log(undefined == null)  // true 
console.log(undefined === null) // false
